<?php

/**
 * @author chenshubo
 * 支付订单申报回调通知
 */
namespace App\Service\OrderService\OrderInterfaceService;

use App\Service\BaseService;
use App\Service\Code\Normal;
use App\Model\PssModel\OrderSupplier;
use App\Model\PssModel\OrderSupplierGoods;
use App\Model\CommodityModel\SupplierCompany;
use App\Model\PssModel\Business;
use App\Service\VendorClient\S2bMoBaoPay\S2bMoBaoPayApiClient;
use App\Service\AppService\PushOrderSettleMentService;

class OrderPayDeclare extends BaseService
{
    private $order_type=[
        'wechat'=>'WechatPayDeclare',
        'alipay',
        'mobao'
    ];

    /**
     * 提交支付单申报(支持微信)
     * @param array $param
     * @return array
     */
    public function index($param = [])
    {
        if( empty($param['requestData']) ) {
            return Normal::returnCode(Normal::FAIL,"requestData参数不能为空");
        }
        $requestData = $param['requestData'];
        
        if( empty($requestData['orderPayType']) ) {
            return Normal::returnCode(Normal::FAIL,"orderPayType支付申报类型不能为空");
        }
        if (!isset($this->order_type[$requestData['orderPayType']])){
            return Normal::returnCode(Normal::FAIL,"orderPayType支付申报类型不支持");
        }
        $supplierPayType=$this->order_type[$requestData['orderPayType']];

        $serviceClass  = "App\\Service\\VendorClient\\OrderPayDeclareService\\{$supplierPayType}\\{$supplierPayType}ApiClient";
       
        if( !class_exists($serviceClass) ) {
            return Normal::returnCode(Normal::FAIL,"{$serviceClass} not existed");
        }
        

        $requestMethod = 'payDeclare';
        if( !method_exists($serviceClass,$requestMethod)) {
            return Normal::returnCode(Normal::FAIL,"{$serviceClass} {$requestMethod} methods not existed");
        }

        //这里保存一下
        $res = $serviceClass::instance()->$requestMethod($requestData);
        if( $res['code'] != Normal::SUC ) {
            return Normal::returnCode($res['code'],"支付单申报服务【{$supplierPayType}】处理失败：【{$res['msg']}】");
        }
        
        return Normal::returnCode(Normal::SUC,"提交申报完成",$res);
    }

    /**
     * 查询申报结果
     */
    public function queryResult($param = [])
    {
        if( empty($param['requestData']) ) {
            return Normal::returnCode(Normal::FAIL,"requestData参数不能为空");
        }

        $requestData = $param['requestData'];

        if( empty($requestData['orderPayType']) ) {
            return Normal::returnCode(Normal::FAIL,"orderPayType支付申报类型不能为空");
        }
        if (!isset($this->order_type[$requestData['orderPayType']])){
            return Normal::returnCode(Normal::FAIL,"orderPayType支付申报类型不支持");
        }
        $supplierPayType=$this->order_type[$requestData['orderPayType']];

        $serviceClass  = "App\\Service\\VendorClient\\OrderPayDeclareService\\{$supplierPayType}\\{$supplierPayType}ApiClient";
        if( !class_exists($serviceClass) ) {
            return Normal::returnCode(Normal::FAIL,"{$serviceClass} not existed");
        }

        $requestMethod = 'payDeclareQuery';
        if( !method_exists($serviceClass,$requestMethod)) {
            return Normal::returnCode(Normal::FAIL,"{$serviceClass} {$requestMethod} methods not existed");
        }

        //这里保存一下
        $res = $serviceClass::instance()->$requestMethod($requestData);
        if( $res['code'] != Normal::SUC ) {
            return Normal::returnCode($res['code'],"支付单申报服务【{$supplierPayType}】查询失败：【{$res['msg']}】");
        }
        return Normal::returnCode(Normal::SUC,"查询成功",$res['data']);
    }

    /**
     * 重新申报
     */
    public function redeclare($param = [])
    {
        if( empty($param['requestData']) ) {
            return Normal::returnCode(Normal::FAIL,"requestData参数不能为空");
        }
        $requestData = $param['requestData'];

        if( empty($requestData['orderPayType']) ) {
            return Normal::returnCode(Normal::FAIL,"orderPayType支付申报类型不能为空");
        }
        if (!isset($this->order_type[$requestData['orderPayType']])){
            return Normal::returnCode(Normal::FAIL,"orderPayType支付申报类型不支持");
        }
        $supplierPayType=$this->order_type[$requestData['orderPayType']];

        $serviceClass  = "App\\Service\\VendorClient\\OrderPayDeclareService\\{$supplierPayType}\\{$supplierPayType}ApiClient";
        if( !class_exists($serviceClass) ) {
            return Normal::returnCode(Normal::FAIL,"{$serviceClass} not existed");
        }

        $requestMethod = 'PayRedeclare';
        if( !method_exists($serviceClass,$requestMethod)) {
            return Normal::returnCode(Normal::FAIL,"{$serviceClass} {$requestMethod} methods not existed");
        }

        //这里保存一下
        $res = $serviceClass::instance()->$requestMethod($requestData);
        if( $res['code'] != Normal::SUC ) {
            return Normal::returnCode($res['code'],"支付单申报服务【{$supplierPayType}】重新申报失败：【{$res['msg']}】");
        }
        return Normal::returnCode(Normal::SUC,"提交申报完成",$res['data']);
    }

    /**
     * 修改订单信息
     */
    public function editPayInfo()
    {
        if( empty($param['requestData']) ) {
            return Normal::returnCode(Normal::FAIL,"requestData参数不能为空");
        }

        $requestData = $param['requestData'];

        if( empty($requestData['orderPayType']) ) {
            return Normal::returnCode(Normal::FAIL,"orderPayType支付申报类型不能为空");
        }
        if (!isset($this->order_type[$requestData['orderPayType']])){
            return Normal::returnCode(Normal::FAIL,"orderPayType支付申报类型不支持");
        }
        $supplierPayType=$this->order_type[$requestData['orderPayType']];

        $serviceClass  = "App\\Service\\VendorClient\\OrderPayDeclareService\\{$supplierPayType}\\{$supplierPayType}ApiClient";
        if( !class_exists($serviceClass) ) {
            return Normal::returnCode(Normal::FAIL,"{$serviceClass} not existed");
        }

        $requestMethod = 'editPayInfo';
        if( !method_exists($serviceClass,$requestMethod)) {
            return Normal::returnCode(Normal::FAIL,"{$serviceClass} {$requestMethod} methods not existed");
        }

        //这里保存一下
        $res = $serviceClass::instance()->$requestMethod($requestData);
        if( $res['code'] != Normal::SUC ) {
            return Normal::returnCode($res['code'],"支付单申报服务【{$supplierPayType}】修改订单信息失败：【{$res['msg']}】");
        }
        return Normal::returnCode(Normal::SUC,"修改成功",$res['data']);

    }
    
    /**
     * 新版本支付接口
     * @param array $param
     */
    public function payDeclareNotify( $param = [] )
    {
        if( empty($param['requestData']) ) {
            return Normal::returnCode(Normal::FAIL,"requestData参数不能为空");
        }
        
        $message = $param['requestData'];
        //判断申报订单号
        if( empty($message['OrderNo']) ) {
            return Normal::returnCode(Normal::FAIL,"OrderNo 参数缺失");
        }
        
        $orderSupplier = OrderSupplier::instance()->info(['supplier_dsn' => $message['OrderNo'],]);
        if( empty($orderSupplier) ) {
            return Normal::returnCode(Normal::FAIL,"未找到对应订单信息");
        }
        
        //判断支付单是否申报成功
        if( $orderSupplier['is_apply'] == 1 ) {
            return Normal::returnCode(Normal::SUC,"当前订单已申报成功");
        }
        
        $order_id = $orderSupplier['id'];
        if( ! $message['ReceiptResult'] ) {
            $where = ['id'=>$order_id];
            $data  = [
                'apply_remark'  => isset($message['ReceiptMessage']) ? $message['ReceiptMessage'] : '申报失败',
                'is_apply'      => 2,//申报失败
                'md'            => time(),
            ];
            OrderSupplier::instance()->edit($where,$data);
            return Normal::returnCode(Normal::SUC,"接收处理成功");
        }
        
        //申报成功之后推送订单给对应上游进行创建订单
        //获取响应支付订单信息
        $res = $this->getSupplierOrderLists($orderSupplier);
        if( $res['code'] != Normal::SUC ) {
            return $res;
        }
        $orderInfo      = $res['data']['orderInfo'];
        $orderGoods     = $res['data']['orderGoods'];
        $supplierInfo   = $res['data']['suppplierInfo'];
        $binfo          = $res['data']['binfo'];
        
        //如果发生售后，直接通知上游发生售后，不进行售后
        if( $orderInfo['after_sale_status'] == 1 ) {
            return Normal::returnCode(Normal::SUC,"当前订单已经发生售后，不需要进行申报业务");
        }
        
        //如果是上游供应商需要进行订单申报，则支付单申报通过之后推送结果给订单申报微服务,//申报中或者已申报成功之后不能进行再次申报
        if( $supplierInfo['OrderDeclare'] == 1 ) {
            
            if( $orderInfo['order_decalre_status'] == 1 ) {
                return Normal::returnCode(Normal::SUC,"当前订单已经申报成功");
            }
            
            if( $orderInfo['order_decalre_status'] == 2 ) {
                return Normal::returnCode(Normal::SUC,"当前订单正在申报中");
            }
        }
        
        //写入请求结果
        OrderSupplier::instance()->startTrans();
        $res = $this->NotifyVirtualMobaoPayOrder($orderInfo);
        if( $res['code'] != Normal::SUC ) {
            OrderSupplier::instance()->rollback();
            return $res;
        }
        
        //修改申报订单状态
        $resDeclare = OrderSupplier::instance()->edit(['id'=>$order_id],[
            'apply_remark'  => isset($message['ReceiptMessage']) ? $message['ReceiptMessage'] : '申报失败',
            'is_apply'      => 1,//申报成功
            'apply_time'    => time(),
            'md'            => time(),
        ]);
        if( ! $resDeclare ) {
            OrderSupplier::instance()->rollback();
            return Normal::returnCode(Normal::FAIL,"修改失败");
        }
        
        $mobaoConfig = config('api.mobao.acount');
        $payConfig = [
            'payWay'            => 1,
            'paySerial'         => $message['ReceiptCode'],
            'payCommanyName'    => $mobaoConfig['PayCompanyName'],
            'payCommanyCode'    => $mobaoConfig['PayCompanyCode'],
            'enterpriseNum'     => $mobaoConfig['EBPCompanyCode'],
            'enterpriseName'    => $mobaoConfig['ebpName'],
        ];
        
        $param = [
            'supplierOrder' => $orderInfo,
            'orderItem'     => $orderGoods,
            'companyInfo'   => $supplierInfo,
            'order'         => $payConfig,
            'binfo'         => $binfo,
            'mode'          => PushOrderSettleMentService::SETTLEMENT_MODE_PAY
        ];
        
        //如果是上游供应商需要进行订单申报，则支付单申报通过之后推送结果给订单申报微服务
        if( $supplierInfo['OrderDeclare'] == 1 ) {
            $res = OrderDeclare::instance()->orderPush($param);
        } else {
            //只需要支付申报的订单，直接推送给到上游供应商， 不需要进行订单进行申报动作
            if ( $orderInfo['is_channel_settlement'] == 1 || $orderInfo['is_supplier_settlement'] ==1 ){
                $res = PushOrderSettleMentService::instance()->addOrderSettleMentLog($param);
            }
            if( $res['code'] != Normal::SUC ) {
                OrderSupplier::instance()->rollback();
                return $res;
            }
            $res = OrderPushSupplier::instance()->pushSupplierOrder($param);
        }
        
        if( $res['code'] != Normal::SUC  ) {
            OrderSupplier::instance()->rollback();
            return $res;
        }
        
        OrderSupplier::instance()->commit();
        return Normal::returnCode(Normal::SUC,$res['msg']);
    }
    
    /**
     * 获取供应商列表
     * @param array $param
     */
    public function getSupplierOrderLists( $param = [] )
    {        
        //获取订单商品
        $order_id = $param['id'];
        $bid      = $param['bid'];
        $company_id = $param['company_id'];
        $orderGoods = OrderSupplierGoods::instance()
        ->select(OrderSupplierGoods::instance()->goods_fields)
        ->where('bid',$bid)
        ->where('order_id',$order_id)
        ->get()
        ->toArray();
        if( empty($orderGoods) ) {
            return Normal::returnCode(Normal::FAIL,"获取订单数据失败");
        }
        
        //获取供应商清单信息
        $SupplierCompanyLists = SupplierCompany::instance()->getSupplierListByIds([$company_id]);
        if( empty($SupplierCompanyLists) ) {
            return Normal::returnCode(Normal::FAIL,"获取供应商信息失败");
        }
        
        return Normal::returnCode(Normal::SUC,"订单数据获取成功",[
            'orderInfo'     => $param,
            'orderGoods'    => $orderGoods,
            'suppplierInfo' => current($SupplierCompanyLists),
            'binfo'         => Business::instance()->getUserInfoByBid($param['bid'])
        ]);
    }
    
    /**
     * 模拟摩宝支付数据
     * @param array $param
     */
    public function NotifyVirtualMobaoPayOrder( $orderInfo = [] )
    {
        //组装摩宝原始请求信息（模拟）
        $res = S2bMoBaoPayApiClient::instance()->OrderPay(['orderInfo' => [$orderInfo],'pay_type'=>1]);
        if( $res['code'] != Normal::SUC ) {
            return Normal::returnCode(Normal::FAIL,"摩宝支付请求数据准备失败【{$res['msg']}】");
        }
        $config = config('api.s2bmobao.acount');
        //组装支付响应成功数据
        $time = time();
        $resMobaoPayNofityMessage = [
            "apiName"       =>  "PAY_RESULT_NOTIFY",
            "notifyTime"    =>  date("YmdHis",$time),
            "tradeAmt"      =>  (float)$orderInfo['real_total_money'],
            "merchNo"       =>  $config['merchNo'],
            "merchParam"    =>  "BMYCSC_ORDER_{$orderInfo['bid']}",
            "orderNo"       =>  $orderInfo['supplier_dsn'],
            "tradeDate"     =>  date("Ymd",$orderInfo['pay_time']),
            "accNo"         =>  $orderInfo['pay_sn'],
            "accDate"       =>  date("YmdHis",$orderInfo['pay_time']),
            "orderStatus"   =>  "1"
        ];
        $resMobaoPayNofityMessage['signMsg']  = md5(S2bMoBaoPayApiClient::instance()->mobao_sign($resMobaoPayNofityMessage).$config['key']);
        $resMobaoPayNofityMessage['notifyType'] = '1';
        //海关查验使用
        $resMobaoPayRequest = OrderSupplier::instance()->edit([
            'id'  => $orderInfo['id'],
        ],[
            'apply_request'         => json_encode($res['data'],JSON_UNESCAPED_UNICODE),
            'apply_request_time'    => $time,
            'apply_response'        => json_encode($resMobaoPayNofityMessage,JSON_UNESCAPED_UNICODE),
            'apply_response_time'   => $time + 5,
        ]);
    
        if( !$resMobaoPayRequest ) {
            return Normal::returnCode(Normal::FAIL,"修改数据失败-1");
        }
    
        return Normal::returnCode(Normal::SUC,"修改成功");
    }
}